package com.nakamachizu.controller;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Logger;

import org.mobylet.core.Mobylet;
import org.mobylet.core.MobyletFactory;
import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.controller.validator.Validators;
import org.slim3.datastore.Datastore;
import org.slim3.util.StringUtil;
import org.slim3.util.TimeZoneLocator;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.nakamachizu.collection.IconNameMap;
import com.nakamachizu.model.LandMarkData;
import com.nakamachizu.model.LineData;
import com.nakamachizu.model.MapData;
import com.nakamachizu.model.MarkData;
import com.nakamachizu.model.MemberData;
import com.nakamachizu.service.MapDataService;
import com.nakamachizu.util.ErrorsUtil;
import com.nakamachizu.util.ForwardUtil;
import com.nakamachizu.util.PocketCloudStringUtil;

public class ModifyController extends Controller {

    List<String> messages;
    private static final Logger log = Logger.getLogger(ModifyController.class.getName());
    private String cmd;
    private String id;
    private String name;
    private String comment;
    private String delete;
    private String delete_commit;
    private String line;
    private String pcIcon;
    
    @Override
    public Navigation run() {
        
        init();
        
        if(StringUtil.isEmpty(id)){
            return redirect("/error");
        }
        Mobylet mobylet = MobyletFactory.getInstance();
        String guid = mobylet.getGuid();
        
        if(StringUtil.isEmpty(guid)){
            return redirect("/error");
        }
        
        Key key = KeyFactory.stringToKey(id);
        MarkData mark = Datastore.get(MarkData.class, key);
        name = mark.getName();
        comment = mark.getComment();
        MapData map = mark.getMapDataRef().getModel();
        String mapKey = map.getAccessKey();
        
        if(MemberData.class.getSimpleName().equals(mark.getMarkType())){
            List<LineData> lineList = map.getLineDataListRef().getModelList();
            if(lineList != null && lineList.size() > 0){
                requestScope("hasLine", true);
            }
        }
        if(LandMarkData.class.getSimpleName().equals(mark.getMarkType())){
            pcIcon = mark.getPcIconName();
            requestScope("isLandMark", true);
        }
        
        if(!StringUtil.isEmpty(cmd) && validate() && guid.equals(mark.getUid())){
            Calendar now = Calendar.getInstance(TimeZoneLocator.get());
            name = requestScope("name");
            comment = requestScope("comment");
            if(LandMarkData.class.getSimpleName().equals(mark.getMarkType())){
                pcIcon = requestScope("pcIcon");
                if(StringUtil.isEmpty(pcIcon)){
                    pcIcon = "landmark/text";
                }
                mark.setPcIconName(pcIcon);
            }
            mark.setName(PocketCloudStringUtil.convertWindows31J(name));
            mark.setComment(PocketCloudStringUtil.convertWindows31J(comment));
            mark.setModifyDate(now.getTime());
            Datastore.put(mark);
            messages.add("更新しました。");
        }else if(!StringUtil.isEmpty(cmd) && !validate() && guid.equals(mark.getUid())){
            name = requestScope("name");
            comment = requestScope("comment");
            if(LandMarkData.class.getSimpleName().equals(mark.getMarkType())){
                pcIcon = requestScope("pcIcon");
            }
        }else if(!StringUtil.isEmpty(delete) && guid.equals(mark.getUid())){
            if(StringUtil.isEmpty(delete_commit)){
                requestScope("id", id);
                requestScope("key", mapKey);
                requestScope("messages", messages);

                return forward(ForwardUtil.forwardJsp("modify_del_confirm.jsp"));
            }else{
                MapDataService mds = new MapDataService();
                // メンバーデータの場合
                if(MemberData.class.getSimpleName().equals(mark.getMarkType())){
                    // ラインだけ
                    if(!StringUtil.isEmpty(line)){
                        List<Key>lline = mds.getDeleteLineData(map, guid);
                        if(lline != null){
                            for(Key lineKey : lline){
                                Datastore.delete(lineKey);
                            }
                            messages.add("ラインを削除しました。再度地図上に表示するには位置情報送信を行ってラインを引いてください。");
                        }
                    // 位置情報とライン両方
                    }else{
                        List<MemberData>mList = map.getMemberDataListRef().getModelList();
                        List<MemberData>newList = new ArrayList<MemberData>();
                        for(MemberData data : mList){
                            if(!id.equals(KeyFactory.keyToString(data.getKey()))){
                                newList.add(data);
                            }
                        }
                        
                        
                        newList = mds.allocateMemberData(newList);
                        Datastore.delete(key);
                        for(MemberData data : newList){
                            Datastore.put(data);
                        }
                        List<Key>lline = mds.getDeleteLineData(map, guid);
                        if(lline != null){
                            for(Key lineKey : lline){
                                Datastore.delete(lineKey);
                            }
                        }
                        messages.add("位置情報を削除しました。再度地図上に表示するには位置情報送信を行ってください。");
                    }
                    
                // ランドマークの場合
                }else{
                    List<LandMarkData>lList = map.getLandMarkDataListRef().getModelList();
                    List<LandMarkData>nList = new ArrayList<LandMarkData>();
                    for(LandMarkData lmd : lList){
                        if(!id.equals(KeyFactory.keyToString(lmd.getKey()))){
                            nList.add(lmd);
                        }
                    }
                    nList = mds.allocateLandMark(nList);
                    Datastore.delete(key);
                    for(LandMarkData lmd : nList){
                        Datastore.put(lmd);
                    }
                    messages.add("ランドマーク「" + mark.getName() + "」を削除しました。");
                }
                requestScope("deleted", true);
            }
        }
        
        requestScope("iconNameMap", IconNameMap.ICON_NAME);
        requestScope("pcIcon", pcIcon);
        requestScope("name", name);
        requestScope("comment", comment);
        requestScope("id", id);
        requestScope("key", mapKey);
        requestScope("messages", messages);
        
        return forward(ForwardUtil.forwardJsp("modify.jsp"));
    }
    
    private void init(){
        cmd = requestScope("cmd");
        delete = requestScope("delete");
        id = requestScope("id");
        delete_commit = requestScope("delete_commit");
        line = requestScope("line");
        pcIcon = requestScope("pcIcon");
        messages = new ArrayList<String>();
    }
    
    protected boolean validate() {
        boolean result = false;
        Validators v = new Validators(request);
        v.add("id", v.required());
        v.add("name", v.required());
        v.add("comment", v.required());
        v.add("name", v.maxlength(10));
        v.add("comment", v.maxlength(100));
        result = v.validate();
        
        return result;
    }
    
    @Override
    protected Navigation handleError(Throwable error) {
        error.printStackTrace();
        log.severe(ErrorsUtil.stackTrace(error));
        return forward("error.jsp");
    }
}
